package com.cskaoyan.controller.wxauthanduser;

import com.cskaoyan.bean.BaseRespVo;
import com.cskaoyan.bean.MemoryBean;
import com.cskaoyan.bean.vo.wxauthanduser.AuthLoginVo;
import com.cskaoyan.bean.vo.wxauthanduser.AuthRegisterVo;
import com.cskaoyan.bean.vo.wxauthanduser.UserInfo;
import com.cskaoyan.service.wxauthanduser.AuthService;
import com.cskaoyan.util.common.Constant;
import com.cskaoyan.util.common.StringUtils;
import com.cskaoyan.util.crypt.CryptUtils;
import com.cskaoyan.util.phoneutil.PhoneUtils;
import com.cskaoyan.util.smsutil.SmsUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.security.util.Password;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author Ajun de BBC
 * @Date 2022/7/18 16:15
 * @Version 1.5
 */

@RestController
@RequestMapping("wx/auth")
public class WxAuthController {

    @Autowired
    AuthService authService;

    @Autowired
    MemoryBean memoryBean;

    /**
     * @Description :微信小程序的用户登录
     * @Param :
     * @Return :
     */
    @RequestMapping("login")
    public BaseRespVo wxAuthLogin(@RequestBody Map map, HttpServletRequest httpServletRequest) {
        String username = (String) map.get("username");
        String password = (String) map.get("password");
        String ip = httpServletRequest.getRemoteAddr();//用户最近一次登录的IP

        UserInfo userInfo = authService.vxAuthLogin(username, password, ip);

        if (userInfo == null) {
            return BaseRespVo.ok(null, "账号密码错误", 700);
        }

        String token = CryptUtils.encryptStr(username + password + "ss");
        assert token != null;
        memoryBean.tokenAndUserId.put(token, userInfo.getId());

        AuthLoginVo authLoginInfo = new AuthLoginVo();
        userInfo.setId(null);
        authLoginInfo.setUserInfo(userInfo);
        authLoginInfo.setToken(token);
        return BaseRespVo.ok(authLoginInfo, "成功", 0);

    }

    /**
     * @Description : 用户退出登录
     * @Param :
     * @Return :
     */
    @RequestMapping("logout")
    public BaseRespVo wxAuthLogout(@RequestHeader(Constant.WX_TOKEN_HEADER) String token) {
        memoryBean.tokenAndUserId.remove(token);
        return BaseRespVo.ok(null, "成功", 0);
    }

    /**
     * @Description : 拒绝微信登录
     * @Param :
     * @Return :
     */
    @RequestMapping("login_by_weixin")
    public BaseRespVo wxAuthLoginByWeixin() {
        return BaseRespVo.ok(null, "错误", -1);
    }

    /**
     * @param 用户的手机号
     * @return 短信发送状态
     * @auther zk
     * @description admin/auth/regCaptcha 发送短信验证码
     */
    @RequestMapping("regCaptcha")
    public BaseRespVo wxAuthRegCaptcha(@RequestBody Map map) {

        String mobile = (String) map.get("mobile");
        Random random = new Random();
        String verificationCode = String.valueOf(random.nextInt(900000) + 100000);
        String sendStatus = SmsUtils.sendSms(verificationCode, mobile);
        if ("发送成功".equals(sendStatus)) {
            memoryBean.mobileAndCode.put(mobile, verificationCode + System.currentTimeMillis());
            return BaseRespVo.ok(null, sendStatus, 0);
        } else if ("电话号码错误".equals(sendStatus)) {
            return BaseRespVo.error(402, sendStatus);
        } else {
            return BaseRespVo.error(702, sendStatus);
        }
    }

    /**
     * @param 用户注册账户
     * @return 注册回显信息
     * @auther zk
     * @description admin/auth/register 微信小程序用户注册
     */
    @RequestMapping("register")
    public BaseRespVo wxAuthRegister(@RequestBody Map map) {

        ConcurrentHashMap<String, String> mobileAndCode = memoryBean.mobileAndCode;

        cleanVerificationCodeGarbage(mobileAndCode);

        String code = (String) map.get("code");
        String mobile = (String) map.get("mobile");

        if (checkSubmittedData(mobileAndCode, code, mobile) != null) {
            return checkSubmittedData(mobileAndCode, code, mobile);
        }

        AuthRegisterVo authRegisterVo = authService.wxAuthRegister(map);

        mobileAndCode.remove(mobile);
        if (authRegisterVo.getUserInfo().getNickName() == null) {
            return BaseRespVo.error(704, "用户名已注册");
        }
        if (authRegisterVo.getUserInfo().getAvatarUrl() == null) {
            return BaseRespVo.error(705, "手机号已注册");
        }
        return BaseRespVo.ok(authRegisterVo, "成功", 0);
    }




    /**
     * @param 重置用户密码
     * @return 成功或失败的信息
     * @auther zk
     * @description admin/auth/reset 微信小程序重置密码
     */
    @RequestMapping("reset")
    public BaseRespVo wxAuthReset(@RequestBody Map map) {

        ConcurrentHashMap<String, String> mobileAndCode = memoryBean.mobileAndCode;

        cleanVerificationCodeGarbage(mobileAndCode);

        String mobile = (String) map.get("mobile");
        String password = CryptUtils.encryptStr((String) map.get("password"));
        String code = (String) map.get("code");

        if (checkSubmittedData(mobileAndCode, code, mobile) != null) {
            return checkSubmittedData(mobileAndCode, code, mobile);
        }

        authService.wxAuthReset(mobile, password);
        mobileAndCode.remove(mobile);

        return BaseRespVo.ok(null, "成功", 0);
    }

    // 遍历mobileAndCode的hashmap，删除过期的垃圾mobile-code键值对数据（5分钟过期）（为减少性能开销每10000次请求触发一次）
    private void cleanVerificationCodeGarbage(ConcurrentHashMap<String, String> mobileAndCode) {
        if (!mobileAndCode.containsKey("times")) {
            mobileAndCode.put("times", String.valueOf(0));
        }
        if (Integer.parseInt(mobileAndCode.get("times")) < 10000) {
            mobileAndCode.put("times", String.valueOf(Integer.parseInt(mobileAndCode.get("times")) + 1));
        } else {
            List<String> keys = new ArrayList<>();
            for (Map.Entry<String, String> entry : mobileAndCode.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (!"times".equals(key)) {
                    long verificationCodeTime = Long.parseLong(value.substring(6));
                    long timeDelay = System.currentTimeMillis() - verificationCodeTime;

                    if (timeDelay > 300000) keys.add(key);
                }
            }
            for (String key : keys) {
                mobileAndCode.remove(key);
            }
            mobileAndCode.put("times", String.valueOf(0));
        }
    }

    // 对用注册或重置密码提交的数据进行检查
    private BaseRespVo checkSubmittedData(ConcurrentHashMap<String, String> mobileAndCode, String code, String mobile) {

        if (StringUtils.isEmpty(code)) {
            return BaseRespVo.error(703, "验证码不能为空");
        }
        if (!PhoneUtils.isChinaPhoneLegal(mobile)) {
            return BaseRespVo.error(707, "手机号格式不正确");
        }
        if (!mobileAndCode.containsKey(mobile)) {
            return BaseRespVo.error(707, "手机号不正确");
        }
        String str = mobileAndCode.get(mobile);
        String verificationCode = (str.substring(0, 6));
        long verificationCodeTime = Long.parseLong(str.substring(6));
        if (!code.equals(verificationCode)) {
            return BaseRespVo.error(703, "验证码错误");
        }
        long timeDelay = System.currentTimeMillis() - verificationCodeTime;
        if (timeDelay > 30000000) {
            mobileAndCode.remove(mobile);
            return BaseRespVo.error(703, "验证码超时");
        }
        return null;
    }

}


